package com.gserver.commons.core.async.scheduled;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gserver.commons.core.manager.AbstractManager;

public abstract class ScheduledTask extends AbstractManager {
	/* 28 */protected static final Logger LOGGER = LoggerFactory
			.getLogger("ScheduledTask");

	/* 30 */private static final ScheduledExecutorService SERVICE = Executors
			.newScheduledThreadPool(5);

	/* 33 */public final Task onceTask = new OnceTask(SERVICE);

	/* 35 */public final Task loopTask = new LoopTask(SERVICE);

	public ScheduledTask() {
		/* 40 */if (Thread.getDefaultUncaughtExceptionHandler() == null) {
			/* 42 */Thread
					.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
						public void uncaughtException(Thread t, Throwable e) {
							/* 48 */ScheduledTask.LOGGER.error(
									"ScheduledTask Uncaught exception in thread ["
											+ t + "]", e);
						}

					});
		}
	}

	public void runOnceTask(IScheduledTaskType taskType, Object source) {
		/* 59 */throw new UnsupportedOperationException("没有重载的此方法，你是不是用错了启动方法？");
	}

	public void runLoopTask(IScheduledTaskType taskType, Object source) {
		/* 67 */throw new UnsupportedOperationException("没有重载的此方法，你是不是用错了启动方法？");
	}

	public static abstract interface IScheduledTaskType {
		public static enum DefaultScheduledTaskType implements
				ScheduledTask.IScheduledTaskType {
			/* 344 */DEFAULT;

		}

	}

	private class LoopTask extends ScheduledTask.Task {
		private LoopTask(ScheduledExecutorService service) {
			/* 323 */super(service);
		}

		public ScheduledFuture<?> startScheduleTask(Runnable runnable,
				float delay) {
			/* 329 */int d = (int) (delay * 1000.0F);
			/* 330 */return this.service.scheduleAtFixedRate(runnable, d, d,
					TimeUnit.MILLISECONDS);
		}

	}

	private class OnceTask extends ScheduledTask.Task {
		private OnceTask(ScheduledExecutorService service) {
			super(service);
		}

		public ScheduledFuture<?> startScheduleTask(Runnable runnable,
				float delay) {
			/* 305 */return this.service.schedule(runnable,
					(int) (delay * 1000.0F), TimeUnit.MILLISECONDS);
		}

	}

	public abstract class Task {
		protected ScheduledExecutorService service;
		/* 81 */protected Map<ScheduledTask.IScheduledTaskType, ScheduledFuture<?>> futures = new ConcurrentHashMap();

		private Task(ScheduledExecutorService service) {
			/* 86 */this.service = service;
		}

		protected void startScheduleOnly(boolean only,
				final ScheduledTask.IScheduledTaskType taskType,
				final Object source, float delay) {
			/* 98 */if (delay <= 0.0F) {
				/* 100 */return;
			}

			/* 103 */if (only) {
				/* 105 */cancel(taskType);
			} else {
				/* 109 */ScheduledFuture future = (ScheduledFuture) this.futures
						.get(taskType);
				/* 110 */if (future != null) {
					/* 112 */if ((future.isDone()) && (future.cancel(false))) {
						/* 114 */this.futures.remove(taskType);
					} else {
						/* 118 */return;
					}
				}

			}

			try {
				/* 126 */Runnable runnable = null;
				/* 127 */if ((this instanceof ScheduledTask.OnceTask)) {
					/* 129 */runnable = new Runnable() {
						public void run() {
							try {
								/* 137 */ScheduledTask.this.runOnceTask(
										taskType, source);
							} catch (Exception e) {
								/* 141 */ScheduledTask.LOGGER.error(
										e.getMessage(), e);
							}
						}

					};
				} else {
					/* 149 */runnable = new Runnable() {
						public void run() {
							try {
								/* 157 */ScheduledTask.this.runLoopTask(
										taskType, source);
							} catch (Exception e) {
								/* 161 */ScheduledTask.LOGGER.error(
										e.getMessage(), e);
							}
						}

					};
				}

				/* 167 */this.futures.put(taskType,
						startScheduleTask(runnable, delay));
			} catch (Exception e) {
				/* 171 */ScheduledTask.LOGGER.error(e.getMessage(), e);
			}
		}

		public void startScheduleOnly(
				ScheduledTask.IScheduledTaskType taskType, Object source,
				float delay) {
			/* 184 */startScheduleOnly(false, taskType, source, delay);
		}

		public void startScheduleOnly(
				ScheduledTask.IScheduledTaskType taskType, float delay) {
			/* 194 */startScheduleOnly(taskType, null, delay);
		}

		public void startScheduleOnly(Object source, float delay) {
			/* 204 */startScheduleOnly(
					ScheduledTask.IScheduledTaskType.DefaultScheduledTaskType.DEFAULT,
					source, delay);
		}

		public void startScheduleOnly(float delay) {
			/* 214 */startScheduleOnly(
					ScheduledTask.IScheduledTaskType.DefaultScheduledTaskType.DEFAULT,
					null, delay);
		}

		public void startSchedule(ScheduledTask.IScheduledTaskType taskType,
				Object source, float delay) {
			/* 224 */startScheduleOnly(true, taskType, source, delay);
		}

		public void startSchedule(ScheduledTask.IScheduledTaskType taskType,
				float delay) {
			/* 234 */startSchedule(taskType, null, delay);
		}

		public void startSchedule(Object source, float delay) {
			/* 244 */startSchedule(
					ScheduledTask.IScheduledTaskType.DefaultScheduledTaskType.DEFAULT,
					source, delay);
		}

		public void startSchedule(float delay) {
			/* 254 */startSchedule(
					ScheduledTask.IScheduledTaskType.DefaultScheduledTaskType.DEFAULT,
					null, delay);
		}

		protected abstract ScheduledFuture<?> startScheduleTask(
				Runnable paramRunnable, float paramFloat);

		public void cancel(ScheduledTask.IScheduledTaskType taskType) {
			/* 269 */ScheduledFuture future = (ScheduledFuture) this.futures
					.remove(taskType);
			/* 270 */if (future != null) {
				/* 274 */future.cancel(false);
			}
		}

		public void cancel() {
			/* 283 */cancel(ScheduledTask.IScheduledTaskType.DefaultScheduledTaskType.DEFAULT);
		}

	}

}
